#include "stdafx.h"
#include "Textgen.h"

#include "Random.h"
#include "Exception.h"
#include "Filesystem.h"
#include "MML.h"

using namespace Cvekas;

uint n_words;
std::vector<std::string> words;
std::vector<uint> freq_sums;
std::vector<uint> freqs;
Random prng;

uint next_word = 0;

void textgenInit()
{
	MML data(Filesystem::readFileToString(Filesystem::redirect("markov.mml")));
	MMLNode& root = data.getRoot();

	if(root.name != "markov_statistics")
		throw EXCEPTION("Markov statistics file is corrupted");

	MMLNode& words_node = root.getChild("words");
	MMLNode& freqs_node = root.getChild("frequencies");
	n_words = boost::lexical_cast<uint>(words_node.value);
	assert(n_words > 0);

	words.assign(n_words, "");
	std::list<MMLNode>::iterator itr = words_node.children.begin();
	for(; itr != words_node.children.end(); ++itr)
	{
		words[boost::lexical_cast<size_t>(itr->value)] = itr->name;
	}

	freq_sums.assign(n_words, 0);
	freqs.assign(n_words*n_words, 0);

	std::vector<std::string> unparsed_freq;
	itr = freqs_node.children.begin();
	for(uint i = 0; itr != freqs_node.children.end(); ++itr, ++i)
	{
		boost::split(unparsed_freq, itr->value, boost::is_any_of(" "));

		uint j = 0, idx = 0;
		while(j < unparsed_freq.size())
		{
			uint idx = boost::lexical_cast<uint>(unparsed_freq[j]);
			uint v = boost::lexical_cast<uint>(unparsed_freq[j+1]);
			j += 2;
			freqs[i*n_words + idx] = v;
			freq_sums[i] += v;
		}
	}
}

void textgenReseed(uint word_idx)
{
	assert(word_idx < n_words);
	next_word = word_idx;
}

std::string textgenWord()
{
	uint current_word = next_word;
	uint r = prng.randUInt(0, freq_sums[current_word]);
	uint sum = 0;
	next_word = 0;
	while(sum <= r) 
	{
		sum += freqs[current_word*n_words + next_word];
		next_word++;
	}
	next_word -= 1;
	return words[current_word];
}